package com.autoswf.core
{
	import flash.errors.IllegalOperationError;
	import flash.utils.Dictionary;
	import flash.utils.getQualifiedClassName;

	
	/**
	 * Extends Link to allow multiple callback hooks to be bound to different Transport implementations. 
	 * Callback return type and value can stop Transport from propagating to parent nodes. 
	 */	
	public class LinkSplice extends Link
	{
		protected var _hooks:Dictionary;
		
		
		/**
		 * Constructor. 
		 */		
		public function LinkSplice(id:String)
		{
			super(id);
		}
		
		override protected function init():void
		{
			super.init();
			
			_hooks = new Dictionary(false);
		}
		
		/** Method is not supported, use addHook. */
		override public function set hook(value:Function):void
		{
			throw new IllegalOperationError("LinkSplice::hook is not supported, use addHook method");
		}
		
		
		/** Add a callback function for a particular transport type. */
		public function addHook(requestDef:Class, func:Function):void
		{
			var className:String = getQualifiedClassName(requestDef);
			_hooks[className] = func;
		}
		
		
		/** Remove the callback function for a transport type. */
		public function removeHook(requestDef:Class):void
		{
			var className:String = getQualifiedClassName(requestDef);
			delete _hooks[className];
		}
		
		
		/**
		 * Allows bound hook return type to determine how and what gets passed to parents.
		 * 
		 * Hook returning void or false will prevent bubbling the message to parents.
		 * Hook returning true or the original transport will bubble the original transport.
		 * Hook returning a new object will bubble the new object (for intercepting/replacing a transport).
		 */
		override public function sendUp(object:*):void
		{
			var transport:Transport = (object is Transport) ? object : new Transport(object);
			
			var classname:String = getQualifiedClassName(transport.message);
			var hook:Function = _hooks[classname];
			
			if(hook != null) /* there is a hook for this object type, proceed */
			{
				var returnVal:* = hook(transport.message);  /* invoke the hook, passing the message */
				if(returnVal)
				{
					if(returnVal is Boolean) /* returnVal is true, notifyParents with original message */
					{
						notifyParents(transport);
					}
					else /* returnVal is an object, bubble that instead */
					{
						if(!(returnVal is Transport))
						{
							returnVal = new Transport(returnVal).setPath(transport.path);
						}
						notifyParents(returnVal);
					}
				}
				/* else returnVal is undefined or false, don't notifyParents */
				
			}
			else /* nothing registered for this object, pass it on */
			{
				notifyParents(transport);
			}
		}
		
	}
}